﻿//#define _CRT_SECURE_NO_WARNINGS
// C/C++ 标准库学习网站：https://legacy.cplusplus.com
// C/C++ 参考学习网站：https://zh.cppreference.com/w/cpp
// C/C++ 微软(Visual Studio)中文学习网站：https://learn.microsoft.com/zh-cn/cpp/cpp/?view=msvc-170
// OpenGl 学习网站：https://docs.gl/
#include "common.h"

//#include <iostream>

#include "MusicPlayer.h"
#include <stdexcept>


void MusicPlayer::init_OpenAL()
{
    // 初始化 OpenAL
    al_device = alcOpenDevice(nullptr);
    if (!al_device) {
        qDebug() << "Failed to open default OpenAL device";
        throw std::runtime_error("Could not open default OpenAL device");
    }

    ALboolean is_supported_ext2 = alIsExtensionPresent("EAX2.0");
    if (is_supported_ext2)
        qDebug() << "EAX2.0 extension is supported";
    else
        qDebug() << "EAX2.0 extension not supported";
    alGetError(); // Clear error code
    //al_debug("")

    // Create context --- 创建上下文
    al_context = alcCreateContext(al_device, nullptr);
    if (!al_context) {
        qDebug() << "Failed to create OpenAL context";
        alcCloseDevice(al_device);
        throw std::runtime_error("Could not create OpenAL context");
    }

    // Set current context --- 设置当前上下文
    if (!alcMakeContextCurrent(al_context)) {
        qDebug() << "Failed to make OpenAL context current";
        alcDestroyContext(al_context);
        alcCloseDevice(al_device);
        throw std::runtime_error("Could not make OpenAL context current");
    }

    // Generate source --- 生成源
    alGenSources(1, &al_source);
    if (alGetError() != AL_NO_ERROR) {
        qDebug() << "Failed to generate OpenAL source";
        alcDestroyContext(al_context);
        alcCloseDevice(al_device);
        throw std::runtime_error("Could not generate OpenAL source");
    }

    // Initialize OpenAL buffers and sources --- 初始化 OpenAL 缓冲区
    alGenBuffers(NUM_BUFFERS, al_buffers);
    if (alGetError() != AL_NO_ERROR) {
        qDebug() << "Failed to generate OpenAL buffer";
        alcDestroyContext(al_context);
        alcCloseDevice(al_device);
        throw std::runtime_error("Could not generate OpenAL buffer");
    }

    // 检查 ALC_EXT_EFX 扩展支持，如果支持，则创建 Reverb 效果
    create_OpenAL_effect();

    // 初始化监听器
    initialize_listener();

    init_set_OpenAL();

    /*ALboolean al_bool = alIsExtensionPresent("AL_EXT_float32");
    qDebug() << "AL_EXT_float32: " << al_bool;*/
}

void MusicPlayer::create_OpenAL_effect()
{
    // 检查 ALC_EXT_EFX 扩展支持
    if (!alcIsExtensionPresent(al_device, "ALC_EXT_EFX")) {
        qDebug() << "ALC_EXT_EFX extension not supported";
        return;
    }
    is_ALC_EXT_EFX_supported = true;
    //qDebug() << "ALC_EXT_EFX extension is supported" << is_ALC_EXT_EFX_supported;
    /*
    if (!alIsExtensionPresent("AL_EXT_FILTER")) {
        qDebug() << "AL_EXT_FILTER extension not supported";
        return;    // 源不支持 AL_EXT_FILTER 扩展
    }
    */

    // 用 alGetProcAddress 获取 EFX 函数指针
    alGenEffects = (LPALGENEFFECTS)alGetProcAddress("alGenEffects");

    // 获取 alDeleteEffects 函数指针
    alDeleteEffects = (LPALDELETEEFFECTS)alGetProcAddress("alDeleteEffects");

    // 获取 alEffecti 函数指针
    alEffecti = (LPALEFFECTI)alGetProcAddress("alEffecti");

    // 获取 alEffectf 函数指针
    alEffectf = (LPALEFFECTF)alGetProcAddress("alEffectf");

    /*
    // Load the alGenFilters function pointer
    alGenFilters = (LPALGENFILTERS)alGetProcAddress("alGenFilters");
    if (!alGenFilters) {
        qDebug() << "Failed to load alGenFilters function pointer";
        throw std::runtime_error("Could not load alGenFilters function pointer");
    }

    // 获取 alDeleteFilters 函数指针
    alDeleteFilters = (LPALDELETEFILTERS)alGetProcAddress("alDeleteFilters");
    if (!alDeleteFilters) {
        qDebug() << "Failed to load alDeleteFilters function pointer";
        throw std::runtime_error("Could not load alDeleteFilters function pointer");
    }

    // 获取 alFilterf 函数指针
    alFilterf = (LPALFILTERF)alGetProcAddress("alFilterf");
    if (!alFilterf) {
        qDebug() << "Failed to load alFilterf function pointer";
        throw std::runtime_error("Could not load alFilterf function pointer");
    }

    // 获取 alFilteri 函数指针
    alFilteri = (LPALFILTERI)alGetProcAddress("alFilteri");
    if (!alFilteri) {
        qDebug() << "Failed to load alFilteri function pointer";
        throw std::runtime_error("Could not load alFilteri function pointer");
    }
    */

    // 获取 alGenAuxiliaryEffectSlots 函数指针
    alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)alGetProcAddress("alGenAuxiliaryEffectSlots");

    // 获取 alDeleteAuxiliaryEffectSlots 函数指针
    alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)alGetProcAddress("alDeleteAuxiliaryEffectSlots");

    // 获取 alAuxiliaryEffectSloti 函数指针
    alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)alGetProcAddress("alAuxiliaryEffectSloti");

    if (!alGenEffects || !alDeleteEffects || !alEffecti || !alEffectf ||
        !alGenAuxiliaryEffectSlots || !alDeleteAuxiliaryEffectSlots || !alAuxiliaryEffectSloti) {
        qDebug() << "Failed to get EFX function pointers";
        return;
    }

    // 创建混响效果对象
    alGenEffects(1, &al_reverb_effect);
    al_debug("Error generating effect")

        // 设置混响效果类型为 Reverb
        alEffecti(al_reverb_effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);

    // 设置效果参数
    // 设置混响密度，取值范围为0.0到1.0，值越大，混响越密集
    alEffectf(al_reverb_effect, AL_REVERB_DENSITY, 0.0f);

    // 设置混响扩散度，取值范围为0.0到1.0，值越大，混响扩散效果越明显
    alEffectf(al_reverb_effect, AL_REVERB_DIFFUSION, 0.0f);

    // 设置混响总增益，取值范围为0.0到1.0，值越大，混响音量越大
    alEffectf(al_reverb_effect, AL_REVERB_GAIN, 0.0f);

    // 设置高频混响增益，取值范围为0.0到1.0，值越大，高频混响音量越大
    alEffectf(al_reverb_effect, AL_REVERB_GAINHF, 0.0f);

    // 设置混响衰减时间，取值范围为0.1到20.0秒，值越大，混响持续时间越长
    alEffectf(al_reverb_effect, AL_REVERB_DECAY_TIME, 0.1f);

    // 设置高频衰减时间比，取值范围为0.1到2.0秒，值越大，高频混响衰减越快
    alEffectf(al_reverb_effect, AL_REVERB_DECAY_HFRATIO, 2.0f);

    // 设置早期反射增益，取值范围为0.0到3.16，值越大，早期反射音量越大
    alEffectf(al_reverb_effect, AL_REVERB_REFLECTIONS_GAIN, 0.0f);

    // 设置早期反射延迟，取值范围为0.0到0.3秒，值越大，早期反射延迟越长
    alEffectf(al_reverb_effect, AL_REVERB_REFLECTIONS_DELAY, 0.0f);

    // 设置晚期混响增益，取值范围为0.0到10.0，值越大，晚期混响音量越大
    alEffectf(al_reverb_effect, AL_REVERB_LATE_REVERB_GAIN, 0.0f);

    // 
    //alEffectf(al_reverb_effect, AL_REVERB_AIR_ABSORPTION_GAINHF, 0.994f);

    // 
    //alEffectf(al_reverb_effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, 0.0f);

    // 
    //alEffecti(al_reverb_effect, AL_REVERB_DECAY_HFLIMIT, AL_TRUE);

    // 设置晚期混响延迟，取值范围为0.0到0.1秒，值越大，晚期混响延迟越长
    //alEffectf(al_reverb_effect, AL_REVERB_LATE_REVERB_DELAY, 0.1f);

    // 设置混响衰减HF限值，取值范围为0.1到1.0，值越大，衰减越快
    //alEffectf(al_reverb_effect, AL_REVERB_AIR_ABSORPTION_GAINHF, 0.908f);

    // 设置混响室大小，取值范围为0.0到100.0，值越大，混响室越大
    //alEffectf(al_reverb_effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, 99.866f);

    // 设置混响衰减HF限值，取值范围为0.1到1.0，值越大，衰减越快
    //alEffectf(al_reverb_effect, AL_REVERB_DECAY_HFLIMIT, 0.824f);
    al_debug("Error setting reverb effect parameters")

        /*
        // 创建低通滤波器对象
        alGenFilters(1, &al_lowpass_filter);
        // 设置低通滤波器参数
        alFilterf(al_lowpass_filter, AL_LOWPASS_GAIN, 1.0f);    // 总增益，通常设为 1.0
        alFilterf(al_lowpass_filter, AL_LOWPASS_GAINHF, 0.5f); // 高频增益，值越小，高频衰减越多
        // 设置低通滤波器类型为 Lowpass
        alFilteri(al_lowpass_filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
        // 将滤波器分配给音频源
        alSourcei(al_source, AL_DIRECT_FILTER, al_lowpass_filter);
        al_debug("Error setting low pass filter type")

        // 创建高通滤波器对象
        alGenFilters(1, &al_highpass_filter);
        // 设置高通滤波器参数
        alFilterf(al_highpass_filter, AL_HIGHPASS_GAIN, 1.0f);    // 总增益，通常设为 1.0
        alFilterf(al_highpass_filter, AL_HIGHPASS_GAINLF, 0.5f); // 低频增益，值越小，低频衰减越多
        // 设置高通滤波器类型为 Highpass
        alFilteri(al_highpass_filter, AL_FILTER_TYPE, AL_FILTER_HIGHPASS);
        // 将滤波器分配给音频源
        alSourcei(al_source, AL_AUXILIARY_SEND_FILTER, al_highpass_filter);
        al_debug("Error setting high pass filter type")
        */

        // 创建辅助效果槽
        // 创建一个辅助效果槽，并将混响效果绑定到它上面
        ALuint aux_effect_slot;
    alGenAuxiliaryEffectSlots(1, &aux_effect_slot);
    al_debug("Error generating auxiliary effect slot")
        alAuxiliaryEffectSloti(aux_effect_slot, AL_EFFECTSLOT_EFFECT, al_reverb_effect);
    al_debug("Error setting effect for auxiliary effect slot")
        // 保存到成员变量
        al_aux_effect_slot = aux_effect_slot;

    alSpeedOfSound(343.0f);
    // 将辅助效果槽附加到 OpenAL 源上
    // 第一个参数是源的 ID (al_source)
    // 第二个参数是属性名 (AL_AUXILIARY_SEND_FILTER)
    // 第三个参数是辅助效果槽的ID (aux_effect_slot)
    // 第四个参数是过滤器的ID（这里设置为0，表示不使用过滤器）
    // 第五个参数是过滤器的偏移量（这里设置为0，表示不使用偏移量）
    alSource3i(al_source,
        AL_AUXILIARY_SEND_FILTER,
        aux_effect_slot, 0, 0);
    al_debug("Error setting auxiliary effect slot for source")
}

template <typename T>
void MusicPlayer::update_affects(T* obj, void (T::* func)(float), float value)
{
    // 调用成员函数，更新混响参数
    (obj->*func)(value);
    // 重新绑定 effect 到 aux slot，确保参数生效
    if (alAuxiliaryEffectSloti && al_aux_effect_slot && al_reverb_effect)
        alAuxiliaryEffectSloti(al_aux_effect_slot, AL_EFFECTSLOT_EFFECT, al_reverb_effect);
}

void MusicPlayer::set_density(float density)
{
    alEffectf(al_reverb_effect, AL_REVERB_DENSITY, density);
}

void MusicPlayer::set_diffusion(float diffusion)
{
    alEffectf(al_reverb_effect, AL_REVERB_DIFFUSION, diffusion);
}

void MusicPlayer::set_gain(float gain)
{
    alEffectf(al_reverb_effect, AL_REVERB_GAIN, gain);
}

void MusicPlayer::set_decay_time(float decay_time)
{
    alEffectf(al_reverb_effect, AL_REVERB_DECAY_TIME, decay_time);
}

void MusicPlayer::set_gainhf(float gainhf)
{
    alEffectf(al_reverb_effect, AL_REVERB_GAINHF, gainhf);
}

void MusicPlayer::set_decay_hfratio(float decay_hfratio)
{
    alEffectf(al_reverb_effect, AL_REVERB_DECAY_HFRATIO, decay_hfratio);
}

void MusicPlayer::set_reflections_gain(float reflections_gain)
{
    alEffectf(al_reverb_effect, AL_REVERB_REFLECTIONS_GAIN, reflections_gain);
}

void MusicPlayer::set_reflections_delay(float reflections_delay)
{
    alEffectf(al_reverb_effect, AL_REVERB_REFLECTIONS_DELAY, reflections_delay);
}

void MusicPlayer::set_late_reverb_gain(float late_reverb_gain)
{
    alEffectf(al_reverb_effect, AL_REVERB_LATE_REVERB_GAIN, late_reverb_gain);
}

void MusicPlayer::initialize_listener()
{
    // Set position --- 设置音源位置
    alSource3f(al_source, AL_POSITION, 0.0f, 0.0f, 0.0f);
    alSourcei(al_source, AL_SOURCE_RELATIVE, AL_FALSE);

    // Set velocity --- 设置音源速度
    alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);

    // 设置距离模型
    alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);

    // 设置监听器方向
    ALfloat listener_orientation[] = {
        0.0f, 0.0f, -1.0f,  // 前方方向
        0.0f, 1.0f,  0.0f  // 上方方向
    };
    alListenerfv(AL_ORIENTATION, listener_orientation);

    // 设置监听器增益，音量了
    alListenerf(AL_GAIN, 1.0f);

    // 输出当前源和监听器的位置以进行验证
    ALfloat source_position[3];
    alGetSource3f(al_source, AL_POSITION, &source_position[0], &source_position[1], &source_position[2]);
    qDebug() << "Source position set to:" << source_position[0] << source_position[1] << source_position[2];

    ALfloat listener_position[3];
    alGetListener3f(AL_POSITION, &listener_position[0], &listener_position[1], &listener_position[2]);
    qDebug() << "Listener position set to:" << listener_position[0] << listener_position[1] << listener_position[2];
}

void MusicPlayer::init_set_OpenAL()
{
    // Set up OpenAL buffers and sources --- 设置 OpenAL 缓冲区和源
    // Set buffer size --- 设置缓冲区大小
    //alBufferf(al_buffers[0], AL_BUFFER, 0.0f);

    // Set gain --- 设置响度
    alSourcef(al_source, AL_GAIN, 1.0f);

    // Set velocity --- 设置速度
    alSource3f(al_source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);

    // Set looping --- 设置循环
    alSourcei(al_source, AL_LOOPING, AL_FALSE);

    // 距离衰减参数（关键！）
    alSourcef(al_source, AL_REFERENCE_DISTANCE, 1723.0f); // 参考距离
    alSourcef(al_source, AL_MAX_DISTANCE, 1000.0f);    // 最大距离
    alSourcef(al_source, AL_ROLLOFF_FACTOR, 200.0f);     // 衰减因子
    alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);

    // Set state --- 设置状态
    alSourcePlay(al_source);

    // 设置监听器位置
    set_listener_coordinate(); // 以后文件修改
}

void MusicPlayer::set_volume(int volume)
{
    if (volume < 0 || volume > 200) {
        qDebug() << "Volume must be between 0 and 200";
    }
    else {
        float gain = static_cast<float>(volume) / 100.0f;
        alSourcef(al_source, AL_GAIN, gain);
    }
}

void MusicPlayer::set_listener_coordinate(float x, float y, float z)
{
    // 设置监听器位置
    alListener3f(AL_POSITION, x, y, z); // 让监听器和音源有一定距离
    alGetError(); // 清除错误
    //al_debug("Error setting listener position")
}

void MusicPlayer::clear_OpenAL_buffers()
{
    //std::lock_guard<std::mutex> lock(player_mutex);
    // 释放 frame_list 资源
    /*for (std::vector<AVFrame*>::iterator it = frame_list.begin(); it < frame_list.end(); ++it)
    av_frame_free(&(*it)); */

    bool play_or_pause = is_playing;
    pause();
    // Unqueue all buffers
    ALint queued = 0;
    alGetSourcei(al_source, AL_BUFFERS_QUEUED, &queued);
    while (queued-- > 0) {
        ALuint bufid = 0;
        alSourceUnqueueBuffers(al_source, 1, &bufid);
    }
    // Delete and recreate buffers
    alDeleteBuffers(NUM_BUFFERS, al_buffers);
    alGenBuffers(NUM_BUFFERS, al_buffers);

    for (auto item : frame_list)
        av_frame_free(&item);
    frame_list.clear();
    alSourceStop(al_source);

    // 释放 SoundTouch 资源
    soundTouch.clear();
    if (play_or_pause)
        play();
}


template<>
ALenum get_openal_format<int16_t>(int channels) {
    if (channels == 1)
        return AL_FORMAT_MONO16;
    if (channels == 2)
        return AL_FORMAT_STEREO16;
    qDebug() << "Unsupported float channel count:" << channels;
    return 0;
}

template<>
ALenum get_openal_format<float>(int channels) {
    if (channels == 1)
        return AL_FORMAT_MONO_FLOAT32;
    if (channels == 2)
        return AL_FORMAT_STEREO_FLOAT32;
    qDebug() << "Unsupported float channel count:" << channels;
    return 0;
}

// 显式实例化模板，解决 LNK2019 链接错误
// 只需实例化 MusicPlayer 成员函数的 float 版本
// 这样链接器就能找到实现
template void MusicPlayer::update_affects(MusicPlayer*, void (MusicPlayer::*)(float), float);
